// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.asm.analysis;

import java.util.List;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Interpreter;
import org.objectweb.asm.tree.analysis.Value;

/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */
public class InterpreterAdapter implements Interpreter {

  private final Interpreter baseInterpreter;

  public InterpreterAdapter(Interpreter baseInterpreter) {
    this.baseInterpreter = baseInterpreter;
  }
  
  public Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2)
      throws AnalyzerException {
    return wrapValueOrNull(baseInterpreter.binaryOperation(insn, value1, value2));
  }

  public Value copyOperation(AbstractInsnNode insn, Value value) throws AnalyzerException {
    return wrapValueOrNull(baseInterpreter.copyOperation(insn, value));
  }

  public Value merge(Value v, Value w) {
    return wrapValueOrNull(baseInterpreter.merge(v, w));
  }

  @SuppressWarnings("unchecked")
  public Value naryOperation(AbstractInsnNode insn, List values) throws AnalyzerException {
    return wrapValueOrNull(baseInterpreter.naryOperation(insn, values));
  }

  public Value newOperation(AbstractInsnNode insn) throws AnalyzerException {
    return wrapValueOrNull(baseInterpreter.newOperation(insn));
  }

  public Value newValue(Type type) {
    return wrapValueOrNull(baseInterpreter.newValue(type));
  }

  public Value ternaryOperation(AbstractInsnNode insn, Value value1, Value value2, Value value3)
      throws AnalyzerException {
    return wrapValueOrNull(baseInterpreter.ternaryOperation(insn, value1, value2, value3));
  }

  public Value unaryOperation(AbstractInsnNode insn, Value value) throws AnalyzerException {
    return wrapValueOrNull(baseInterpreter.unaryOperation(insn, value));
  }
  
  /**
   * Wraps value returned from base interpreter.
   * 
   * @param value value returned from base interpreter, may be null.
   * @return wrapped value, may be null.
   */
  private Value wrapValueOrNull(Value value) {
    if (value != null) {
      value = wrapValue(value);
    }
    return value;
  }

  /**
   * Wraps value returned from base interpreter.
   * 
   * @param value value returned from base interpreter.
   * @return wrapped value.
   */
  protected Value wrapValue(Value value) {
    return value;
  }
}
